<?php
/**
 * ShopEx licence
 *
 * @copyright  Copyright (c) 2005-2010 ShopEx Technologies Inc. (http://www.shopex.cn)
 * @license  http://ecos.shopex.cn/ ShopEx License
 */
 

/*
 * @package base
 * @copyright Copyright (c) 2010, shopex. inc
 * @author edwin.lzh@gmail.com
 * @license 
 */
class base_kvstore_redis2 extends base_kvstore_abstract implements base_interface_kvstore_base,base_interface_kvstore_extension
{
    static private $_cacheObj;

    function __construct($prefix)
    {
        $this->connect();
        $this->prefix = $prefix;
    }//End Function

    public function connect() 
    {
        if(!isset(self::$_cacheObj))
        {
            if(defined('KVSTORE_REDIS_CONFIG') && constant('KVSTORE_REDIS_CONFIG'))
            {
                self::$_cacheObj = new Redis();
                $config = explode(':', KVSTORE_REDIS_CONFIG);
                self::$_cacheObj->connect($config[0], $config[1]);
                if(defined('KVSTORE_REDIS_PASSWORD')) {
                    self::$_cacheObj->auth(KVSTORE_REDIS_PASSWORD);
                }
                $dbname = defined('KVSTORE_REDIS_SELECT')?KVSTORE_REDIS_SELECT:1;
                self::$_cacheObj->select($dbname);
            } else {
                trigger_error('Can\'t load KVSTORE_REDIS_CONFIG, please check it', E_USER_ERROR);
            }
        }
    }//End Function

    public function selects($dbname)
    {
        self::$_cacheObj->select($dbname);
    }

    public function fetch($key, &$value, $timeout_version=null)
    {
//        $store = self::$_cacheObj->get($this->create_key($key));
        $store = self::$_cacheObj->get($key);
        $store = json_decode($store,true);
        if($store !== false)
        {
            if($timeout_version < $store['dateline'])
            {
                if($store['ttl'] > 0 && ($store['dateline']+$store['ttl']) < time()){
                    return false;
                }
                $value = $store['value'];
                return true;
            }
        }
        return false;
    }//End Function

    public function store($key, $value, $ttl=0)
    {
        $store['value'] = $value;
        $store['dateline'] = time();
        $store['ttl'] = $ttl;
//        return self::$_cacheObj->set($this->create_key($key), json_encode($store));
        return self::$_cacheObj->set($key, json_encode($store));
    }//End Function

    public function delete($key,$surce = 0)
    {
        if($surce) {
            return self::$_cacheObj->delete($key);
        }else{
            return self::$_cacheObj->delete($this->create_key($key));
        }
    }//End Function

    public function recovery($record)
    {
        $key = $record['key'];
        $store['value'] = $record['value'];
        $store['dateline'] = $record['dateline'];
        $store['ttl'] = $record['ttl'];
        return self::$_cacheObj->set($this->create_key($key), json_encode($store));
    }//End Function

    public function increment($key, $offset=1)
    {
        $real_key = $this->create_key($key);
        return self::$_cacheObj->incr($real_key, $offset);
    }//End Function

    public function decrement($key, $offset=1)
    {
        $real_key = $this->create_key($key);
        return self::$_cacheObj->decr($real_key, $offset);
    }//End Function

//    public function exists($key){
//        if($key){
//            return self::$_cacheObj->exists($key);
//        }
//    }
    //+++-------------------------集合操作-------------------------+++//

    /**
     * 将value写入set集合 如果value存在 不写入 返回false
     * 如果是有序集合则根据score值更新该元素的顺序
     * @param $set string 集合名
     * @param $value mixed 值
     * @param $stype int 集合类型 0:无序集合 1:有序集和 默认0
     * @param $score int 元素排序值
     */
    public function setAdd($set,$value=null,$stype=0,$score=null)
    {
        $return = null;

        if ($stype && $score !== null) {
            $return = self::$_cacheObj->zAdd($set, $score, $value);
        } else {
            $return = self::$_cacheObj->sAdd($set, $value);
        }

        return $return;
    }

    /**
     * 移除set1中的value元素 如果指定了set2 则将该元素写入set2
     * @param $set1 string 集合名
     * @param $value mixed 值
     * @param $stype int 集合类型 0:无序集合 1:有序集和 默认0
     * @param $set2 string 集合名
     */
    public function setMove($set1, $value=null, $stype=0, $set2=null)
    {
        $return = null;

        if ($set2) {
            $return = self::$_cacheObj->sMove($set1, $set2, $value);
        } else {
            if ($stype) $return = self::$_cacheObj->zRem($set1, $value);
            else $return = self::$_cacheObj->sRem($set1, $value);
        }

        return $return;
    }

    /**
     * 查询set中是否有value元素
     * @param $set string 集合名
     * @param $value mixed 值
     */
    public function setSearch($set, $value=null)
    {
        $return = null;

        $return = self::$_cacheObj->sIsMember($set, $value);

        return $return;
    }

    /**
     * 返回set中所有元素个数 有序集合要指定$stype=1
     * 如果是有序集合并指定了$start和$end 则返回score在start跟end之间的元素个数
     * @param $set string 集合名
     * @param $stype int 集合类型 0:无序集合 1:有序集和 默认0
     * @param $start int 开始index
     * @param $end int 结束index
     */
    public function setSize($set,$stype=0,$start=0,$end=0)
    {
        $return = null;

        if ($stype) {
            if ($start && $end) $return = self::$_cacheObj->zCount($set, $start, $end);
            else $return = self::$_cacheObj->zSize($set);
        } else {
            $return = self::$_cacheObj->sSize($set);
        }

        return $return;
    }

    /**
     * 随机返回set中一个元素，并可选是否删除该元素
     * @param $set string 集合名
     * @param $isdel int 是否删除该元素 0:不删除 1:删除 默认为0
     */
    public function setPop($set,$isdel=0)
    {
        $return = null;

        if ($isdel) {
            $return = self::$_cacheObj->sPop($set);
        } else {
            $return = self::$_cacheObj->sRandMember($set);
        }

        return $return;
    }

    /**
     * 求交集 并可选是否将交集保存到新集合
     * @param $set array 集合名数组
     * @param $newset string 要保存到的集合名 默认为null 即不保存交集到新集合
     * @param $stype int 集合类型 0:无序集合 1:有序集和 默认0
     * @param $weight array 权重 执行function操作时要指定的每个集合的相同元素所占的权重 默认1
     * @param $function string 不同集合的相同元素的取值规则函数 SUM:取元素值的和 MAX:取最大值元素 MIN:取最小值元素
     */
    public function setInter($set,$newset=null,$stype=0,$weight=array(1),$function='SUM')
    {
        $return = array();

        if (is_array($set) && !empty($set)) {
            if ($newset) {
                if ($stype) $return = self::$_cacheObj->zInter($newset, $set, $weight, $function);
                else $return = self::$_cacheObj->sInterStore($newset, $set);
            } else {
                $return = self::$_cacheObj->sInter($set);
            }
        }

        return $return;
    }

    public function setInter2($set,$newset=null,$stype=0,$weight=array(1),$function='SUM')
    {
        $return = array();

        if (is_array($set) && !empty($set)) {
            if ($newset) {
                if ($stype) $return = self::$_cacheObj->zInter($newset, $set, $weight, $function);
                else $return = self::$_cacheObj->sInterStore($set);
            } else {
                $return = self::$_cacheObj->sInter($set);
            }
        }

        return $return;
    }

    /**
     * 求并集 并可选是否将交集保存到新集合
     * @param $set array 集合名数组
     * @param $newset string 要保存到的集合名 默认为null 即不保存交集到新集合
     * @param $stype int 集合类型 0:无序集合 1:有序集和 默认0
     * @param $weight array 权重 执行function操作时要指定的每个集合的相同元素所占的权重 默认1
     * @param $function string 不同集合的相同元素的取值规则函数 SUM:取元素值的和 MAX:取最大值元素 MIN:取最小值元素
     */
    public function setUnion($set,$newset=null,$stype=0,$weight=array(1),$function='SUM')
    {
        $return = array();

        if (is_array($set) && !empty($set)) {
            if ($newset) {
                if ($stype) $return = self::$_cacheObj->zUnion($newset, $set, $weight, $function);
                else $return = self::$_cacheObj->sUnionStore($newset, $set);
            } else {
                $return = self::$_cacheObj->sUnion($set);
            }
        }

        return $return;
    }

    public function setUnion2($set,$newset=null,$stype=0,$weight=array(1),$function='SUM')
    {
        $return = array();

        if (is_array($set) && !empty($set)) {
            if ($newset) {
                if ($stype) $return = self::$_cacheObj->zUnion($newset, $set, $weight, $function);
                else $return = self::$_cacheObj->sUnionStore($set);
            } else {
                $return = self::$_cacheObj->sUnion($set);
            }
        }

        return $return;
    }

    /**
     * 求差集 并可选是否将交集保存到新集合
     * @param $set array 集合名数组
     * @param $newset string 要保存到的集合名 默认为null 即不保存交集到新集合
     */
    public function setDiff($set,$newset=null)
    {
        $return = array();

        if (is_array($set) && !empty($set)) {
            if ($newset) {
                $return = self::$_cacheObj->sDiffStore($newset, $set);
            } else {
                $return = self::$_cacheObj->sDiff($set);
            }
        }

        return $return;
    }

    /**
     * 返回set中所有元素
     * @param $set string 集合名
     */
    public function setMembers($set)
    {
        $return = null;

        $return = self::$_cacheObj->sMembers($set);

        return $return;
    }

    /**
     * 排序 分页等
     * @param $set string 集合名
     * @param $option array 选项
     */
    public function setSort($set,$option)
    {
        $return = null;
        $default_option = array(
            'by'    => 'some_pattern_*', //要匹配的排序value值
            'limit' => array(0, 1), //array(start,length)
            'get'   => 'some_other_pattern_*', //多个匹配格式:array('some_other_pattern1_*','some_other_pattern2_*')
            'sort'  => 'asc', // asc|desc 默认asc
            'alpha' => TRUE, //
            'store' => 'some_need_pattern_*' //永久性排序值
        );

        $option = array_merge($default_option, $option);

        $return = self::$_cacheObj->sort($set, $option);

        return $return;
    }


    //未实现的redis方法调原生
    public function __call($name, $arguments)
    {
        return   call_user_func_array(array(self::$_cacheObj,$name),$arguments);
    }

}//End Class

